/*
 * @Description: 二次封装Axios
 * @Author: Yong
 * @Date: 2021-09-24 10:42:21
 * @LastEditTime: 2021-09-27 19:51:16
 */
import axios from 'axios'
import { Toast } from 'antd-mobile'
import { BASE_URL } from './url'
import { getToken, removeToken } from './auth'


const Axios = axios.create({
    baseURL: BASE_URL,    // 基础路径
    timeout: 20000, // 设置超时时间
})

// 设置post请求头
Axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'

// 当前正在请求的数量
let requestCount = 0

// 显示loading
function showLoading () {
    if (requestCount === 0) {
        Toast.loading('加载中...', 8000, () => { }, true)
    }
    requestCount++
}

// 隐藏loading
function hideLoading () {
    requestCount--
    if (requestCount === 0) {
        Toast.hide()
    }
}

// 白名单 - 当前接口不需要添加Authorization
const whiteURL = ['/user/login', '/user/registered']

// 请求前拦截
Axios.interceptors.request.use(config => {
    if (config.headers.isLoading !== false) {
        showLoading()
    }
    const { url } = config
    if (url.startsWith('/user') && whiteURL.indexOf(url) <= -1) {
        // 添加请求头Token认证
        config.headers.Authorization = getToken()
    }
    return config
}, err => {
    // 判断当前请求是否设置了不显示Loading
    if (err.config.headers.isLoading !== false) {
        hideLoading()
    }
    return Promise.reject(err)
})

// 返回后拦截
Axios.interceptors.response.use(res => {
    // 判断当前请求是否设置了不显示Loading
    if (res.config.headers.isLoading !== false) {
        hideLoading()
    }
    return res
}, err => {
    if (err.config.headers.isLoading !== false) {
        hideLoading()
    }
    return Promise.reject(err)
})

/**
 * 封装get方法
 * @param url  请求url
 * @param params  请求参数
 * @returns {Promise}
 */
export function GET (url, params = {}, headers = {}) {
    return new Promise((resolve, reject) => {
        Axios({ method: 'get', headers, url, params }).then(res => {
            const { data: { status, description, body } } = res
            if (status !== 200) {
                // 错误处理
                msgErr(description, status)
                reject({ err: { errMsg: description } })
            } else {
                if (!headers.isGetAllData) resolve(body)
                else resolve(res.data)
            }
        }).catch(err => {
            msgErr()
            reject(err)
        })
    })
}

/**
 * 封装post请求
 * @param url
 * @param data
 * @returns {Promise}
 */

export function POST (url, data, headers = {}) {
    return new Promise((resolve, reject) => {
        Axios({ method: 'post', headers, url, data }).then(res => {
            const { data: { status, description, body } } = res
            if (status !== 200) {
                // 错误处理
                msgErr(description, status)
                reject({ err: { errMsg: description } })
            } else {
                if (!headers.isGetAllData) resolve(body)
                else resolve(res.data)
            }
        }).catch(err => {
            msgErr()
            reject(err)
        })
    })
}

/**
 * 封装delete请求
 * @param url
 * @param data
 * @returns {Promise}
 */

export function DELETE (url, data, headers = {}) {
    return new Promise((resolve, reject) => {
        Axios({ method: 'delete', headers, url, data }).then(res => {
            const { data: { status, description, body } } = res
            if (status !== 200) {
                // 错误处理
                msgErr(description, status)
                reject({ err: { errMsg: description } })
            } else {
                if (!headers.isGetAllData) resolve(body)
                else resolve(res.data)
            }
        }).catch(err => {
            msgErr()
            reject(err)
        })
    })
}

/**
 * 封装PATCH请求
 * @param url
 * @param data
 * @returns {Promise}
 */

export function PATCH (url, data, headers = {}) {
    return new Promise((resolve, reject) => {
        Axios({ method: 'patch', headers, url, data }).then(res => {
            const { data: { status, description, body } } = res
            if (status !== 200) {
                // 错误处理
                msgErr(description, status)
                reject({ err: { errMsg: description } })
            } else {
                if (!headers.isGetAllData) resolve(body)
                else resolve(res.data)
            }
        }).catch(err => {
            msgErr()
            reject(err)
        })
    })
}

// 统一接口处理，返回数据
export function Http (method, url, param, headers = {}) {
    return new Promise((resolve, reject) => {
        switch (method) {
            case 'get':
                console.log("begin a GET request, and url:", url)
                GET(url, param, headers).then(res => {
                    resolve(res)
                }).catch(err => {
                    console.log("get request GET failed.", err)
                    reject(err)
                })
                break
            case 'post':
                console.log("begin a POST request, and url:", url)
                POST(url, param, headers).then(res => {
                    resolve(res)
                }).catch(err => {
                    console.log("get request POST failed.", err)
                    reject(err)
                })
                break
            case 'delete':
                console.log("begin a DELETE request, and url:", url)
                DELETE(url, param, headers).then(res => {
                    resolve(res)
                }).catch(err => {
                    console.log("get request DELETE failed.", err)
                    reject(err)
                })
                break
            case 'patch':
                console.log("begin a PATCH request, and url:", url)
                PATCH(url, param, headers).then(res => {
                    resolve(res)
                }).catch(err => {
                    console.log("get request PATCH failed.", err)
                    reject(err)
                })
                break
            default:
                break
        }
    })
}

/**
 * 状态码 - 错误处理
 * @param err 
 */
function msgErr (errMsg = '', status = 200) {
    const ToastFail = (content, duration = 2, cb = null, mark = false) => {
        Toast.fail(content, duration, cb, mark)
    }
    switch (status) {
        case 400:
            ToastFail(errMsg)
            // 此时，说明 token 失效，直接移除 token 即可
            removeToken()
            break

        case 401:
            ToastFail("未授权，请登录")
            break

        case 403:
            ToastFail("拒绝访问")
            break

        case 404:
            ToastFail("请求地址出错")
            break

        case 408:
            ToastFail("请求超时")
            break

        case 500:
            ToastFail("服务器内部错误")
            break

        case 501:
            ToastFail("服务未实现")
            break

        case 502:
            ToastFail("网关错误")
            break

        case 503:
            ToastFail("服务不可用")
            break

        case 504:
            ToastFail("网关超时")
            break

        case 505:
            ToastFail("HTTP版本不受支持")
            break
        default:
            ToastFail("网络出小差...")
    }
}